package com.dycong.common.algorithms;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

/**
 * Created by Duke on 2016/9/13.
 */

public class TestFinal {
    public static void main(String[] args) {
        int size = 8;
        /*LongStream.range(0, factorial(size)).forEach(i -> log.info(getNumberOrder(i, size)));

        log.info(getNumberOrder(factorial(20) - 15, 20));*/
        LongStream.range(0, factorial(size)).forEach(i -> System.out.println(getNumberOrder(i, size)));

        System.out.println(getNumberOrder(factorial(20) - 15, 20));
    }

    public static List<Integer> getNumberOrder(long index, int size) throws IllegalArgumentException {                  //index设为long型，没有了为int型时的size=<12的限制！
        if (size > 32 || index > factorial(size)) {                                                         //先判断条件，不符合直接抛出异常，不必再执行下边代码。也省了else！
            throw new IllegalArgumentException("size must less than 32, and index less than factorial(size)");
        }
        List<Integer> list = IntStream.rangeClosed(1, size).boxed().collect(Collectors.toList());
        List<Integer> result = getResult(new ArrayList<>(), list, index, size);
        return result;
    }

    public static List<Integer> getResult(List<Integer> result, List<Integer> remain, long index, int size) {               //参数的传递，使用借口List,不应该使用具体实现类！
        if (size == 1) {
            result.add(remain.get(0));
            return result;
        } else {
            long dg = factorial((--size));
            int i = (int) (index / dg);
            result.add(remain.remove(i));                                           //ArrayList的remove方法会返回移除的值！
            return getResult(result, remain, index % dg, size);
        }
    }

    public static long factorial(int base) {
        if(base < 0)
            throw new IllegalArgumentException("base must at lest 0");
        if (base <= 1) {
            return base;
        } else {
            return base * factorial(base - 1);
        }
    }

}
